package com.jml.AQS;


import java.util.concurrent.CountDownLatch;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;

public class 手写CountDownLatch {


    private MySync mySync;

    public 手写CountDownLatch(int count) {
        mySync = new MySync(count);
    }

    public void await() throws InterruptedException {
        mySync.acquireSharedInterruptibly(1);
    }

    public void countDown() {
        mySync.releaseShared(1);
    }

    class MySync extends AbstractQueuedSynchronizer {
        public MySync(int count) {
            setState(count);
        }


        /**
         * 在wait的时候如果AQS的state大于0，则应该阻塞线程，把线程放入双向链表中进行等待
         * 如果状态小于=0的情况下 则不需要阻塞线程，如果>0的情况下，则需要阻塞当前线程
         */
        @Override
        protected int tryAcquireShared(int arg) {
            return getState() <= 0 ? 1 : -1;
        }

        @Override
        protected boolean tryRelease(int arg) {
            return super.tryRelease(arg);
        }

        @Override
        protected boolean tryReleaseShared(int arg) {
            for (; ; ) {
                int state = getState();
                //如果 state 已经小于等于0了，说明等待线程已经被唤醒了。就不用这个线程来再次唤醒了
                if (state <= 0) {
                    return false;
                }
                int nextS = state - arg;
                if (compareAndSetState(state, nextS)) {
                    return nextS <= 0;//这时如果小于等于0，就应该去唤醒等待线程了
                }
            }
        }


    }

    public static void main(String[] args) throws InterruptedException {
        CountDownLatch countDownLatch = new CountDownLatch(1);
        countDownLatch.await();
        countDownLatch.countDown();
    }

}
